package com.easyssh.framework.common.utils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

import org.apache.commons.beanutils.PropertyUtils;

import com.easyssh.framework.annotation.Operalog;
import com.easyssh.framework.entity.NullEntity;
import com.easyssh.framework.enums.EasyEnum;

public class LogUtils {
	
	/**
	 * 记录日志
	 * @author liangyuanbing
	 * @param logType
	 * @param before, 如果是新增，则设置before为null
	 * @param after
	 * @throws Exception
	 */
	public static String generateLogMsg(Object before, Object after) {
		if(after == null) { //不管是新增还是修改 after都必须有值
			throw new IllegalArgumentException("after is null");
		}
		
		if(before == null) { //新建
			return logCreate(after, new String[]{});
		} else { //修改
			return logUpdate(before, after, new String[]{});
		}	
	}
	
	public static String generateLogMsg(Object before, Object after, String[] excludeProps) {
		if(after == null) { //不管是新增还是修改 after都必须有值
			throw new IllegalArgumentException("after is null");
		}
		
		if(before == null) { //新建
			return logCreate(after, excludeProps);
		} else { //修改
			return logUpdate(before, after, excludeProps);
		}	
	}
	
	private static String logCreate(Object obj, String[] excludeProps) {
		Field[] fields = obj.getClass().getDeclaredFields();
		List<String> props = Arrays.asList(excludeProps);
		StringBuffer logs = new StringBuffer();
		Object afterValue = null;
		
		for(int i = 0; i < fields.length; i++) {
			if(props.indexOf( fields[i].getName() ) >= 0) { //包含在排除的字段列表之内 就跳过
				continue;
			}
			Operalog operLog = fields[i].getAnnotation(Operalog.class);
			if(operLog == null) 
				continue;
			
			try {
				afterValue = PropertyUtils.getSimpleProperty(obj, fields[i].getName());
			} catch(Exception e) {
				throw new RuntimeException(e);
			}
			
			String i18nKey = operLog.i18nKey();
			List<String> constKeys = longToString( operLog.constKeys() );
			String[] constTexts = operLog.constTexts();
			String i18nName = i18nKey; 
			
			if(afterValue instanceof Date) {
				afterValue = DateUtil.formatAll((Date) afterValue);
			}
			if(afterValue instanceof NullEntity ) {
				afterValue = ((NullEntity) afterValue).getId();
			}
			
			if(afterValue == null) {
				afterValue = "";
			}
			
			if(constKeys.isEmpty()) { //表明值不是常量
				logs.append(i18nName + ":" + afterValue + ";<br/>");
			} else {
				logs.append(i18nName + ":" + keyToText(afterValue.toString(), constKeys, constTexts) + ";<br/>");
			}
		}
		
		if(logs.toString().endsWith(";<br/>")) {
			return logs.toString().substring(0, logs.length() - 2);
		} else {
			return logs.toString();
		}
	}
	
	private static String logUpdate(Object before, Object after, String[] excludeProps) {
		List<String> props = Arrays.asList(excludeProps);
		StringBuffer logs = new StringBuffer();
		Field[] fields = before.getClass().getDeclaredFields();
		
		Object beforeValue = null; 
		Object afterValue = null;
		
		for(int i = 0; i < fields.length; i++) {
			if(props.indexOf( fields[i].getName() ) >= 0) { //包含在排除的字段列表之内 就跳过
				continue;
			}
			Operalog operLog = fields[i].getAnnotation(Operalog.class);
			if(operLog == null) 
				continue;
			
			try {
				beforeValue = PropertyUtils.getSimpleProperty(before, fields[i].getName());
				afterValue = PropertyUtils.getSimpleProperty(after, fields[i].getName());
			} catch(Exception e) {
				throw new RuntimeException(e);
			}
			
			Class<?> fieldType = fields[i].getType();
			String typeName = fieldType.getCanonicalName();
			String i18nKey = operLog.i18nKey();
			List<String> constKeys = longToString( operLog.constKeys() );
			String[] constTexts = operLog.constTexts();
			String i18nName = i18nKey; 
			
			if(fieldType.isEnum()){
			    if(beforeValue instanceof EasyEnum && afterValue instanceof EasyEnum && !compareValue((EasyEnum)beforeValue,(EasyEnum)afterValue)){
			    	continue;
			    }
			}
			
			if((beforeValue == null && afterValue == null) || !compareValue(beforeValue, afterValue, typeName))  {
				continue;
			}
			
			if(typeName.equals("java.util.Date")) {
				if(beforeValue != null) {
					beforeValue = DateUtil.formatAll((Date) beforeValue);
				}
				if(afterValue != null) {
					afterValue = DateUtil.formatAll((Date) afterValue);
				}
			}
			if(fieldType.isEnum()&&beforeValue instanceof EasyEnum){
				beforeValue=((EasyEnum)beforeValue).getValue();
			}
			
			if(fieldType.isEnum()&&afterValue instanceof EasyEnum){
				afterValue=((EasyEnum)afterValue).getValue();
			}
			if(beforeValue instanceof NullEntity) {
				beforeValue = ((NullEntity) beforeValue).getId();
			}
			if(afterValue instanceof NullEntity) {
				afterValue = ((NullEntity) afterValue).getId();
			}
			if(beforeValue == null) { beforeValue = ""; }
			if(afterValue == null) { afterValue = ""; }
			
			if(constKeys.isEmpty()) {//表明值不是常量
				logs.append(i18nName + ":" + beforeValue + "-->" + afterValue + ";<br/>");
			} else {
				logs.append(i18nName + ":" + keyToText(beforeValue.toString(), constKeys, constTexts) + "-->" + keyToText(afterValue.toString(), constKeys, constTexts) + ";<br/>");
			}
		}
		
		if(logs.toString().endsWith(";<br/>")) {
			return logs.toString().substring(0, logs.length() - 2);
		} else {
			return logs.toString();
		}
		
	}
	
	public static String changeToString(Object beforeValue, Object afterValue, String typeName, 
			String i18nName, int[] keys, String[] constTexts) {
		StringBuilder sb = new StringBuilder();
		List<String> constKeys = longToString(keys);
		if((beforeValue == null && afterValue == null) || !compareValue(beforeValue, afterValue, typeName))  {
			return sb.toString();
		}
		
		if(typeName.equals("java.util.Date")) {
			if(beforeValue != null) {
				beforeValue = DateUtil.formatAll((Date) beforeValue);
			}
			if(afterValue != null) {
				afterValue = DateUtil.formatAll((Date) afterValue);
			}
		}
		if(beforeValue instanceof NullEntity) {
			beforeValue = ((NullEntity) beforeValue).getId();
		}
		if(afterValue instanceof NullEntity) {
			afterValue = ((NullEntity) afterValue).getId();
		}
		if(beforeValue == null) { beforeValue = ""; }
		if(afterValue == null) { afterValue = ""; }
		
		if(constKeys.isEmpty()) {//表明值不是常量
			sb.append(i18nName + ":" + beforeValue + "-->" + afterValue + ";<br/>");
		} else {
			sb.append(i18nName + ":" + keyToText(beforeValue.toString(), constKeys, constTexts) + "-->" + keyToText(afterValue.toString(), constKeys, constTexts) + ";<br/>");
		}
		
		if(sb.toString().endsWith(";<br/>")) {
			return sb.toString().substring(0, sb.length() - 2);
		} else {
			return sb.toString();
		}
	}
	
	public static boolean compareValue(EasyEnum beforeValue, EasyEnum afterValue) {
		boolean isChange = false;
		if(beforeValue == null && afterValue != null) {
			isChange = true;
		}else if(beforeValue != null && afterValue == null) {
			isChange = true;
		}else{
			isChange=beforeValue.getValue()!=afterValue.getValue();
		}
		return isChange;
	}


	public static boolean compareValue(Object beforeValue, Object afterValue, String typeName) {
		boolean isChange = false;
		if(beforeValue == null && afterValue != null) {
			isChange = true;
		}else if(beforeValue != null && afterValue == null) {
			isChange = true;
		} else {
			isChange = compareValue(beforeValue, afterValue, typeName, isChange);
		}
		return isChange;
	}

	private static boolean compareValue(Object beforeValue, Object afterValue, String typeName, boolean isChange) {
		if (typeName.equals("java.lang.String")) {
			if(!beforeValue.equals(afterValue)) {
				isChange = true;
			}
			
		} else if (typeName.equals("boolean") || typeName.equals("java.lang.Boolean")) {
			if((!(Boolean)beforeValue && (Boolean)afterValue) || ((Boolean)beforeValue && !(Boolean)afterValue)) {
				isChange=true;
			}
			
		} else if (typeName.equals("int") || typeName.equals("java.lang.Integer")) {
			if((Integer)beforeValue - (Integer)afterValue != 0) {
				isChange = true;
			}
			
		} else if (typeName.equals("short") || typeName.equals("java.lang.Short")) {
			if((Short)beforeValue - (Short)afterValue != 0) {
				isChange = true;
			}

		} else if (typeName.equals("long") || typeName.equals("java.lang.Long")) {
			if((Long)beforeValue - (Long)afterValue != 0L) {
				isChange = true;
			}

		} else if (typeName.equals("double") || typeName.equals("java.lang.Double")) {
			if((Double)beforeValue - (Double)afterValue != 0D) {
				isChange = true;
			}
			
		} else if (typeName.equals("float") || typeName.equals("java.lang.Float")){
			if((Float)beforeValue - (Float)afterValue != 0F) {
				isChange = true;
			}

		} else if (typeName.equals("java.util.Date")) {
			String beforeTime =DateUtil.formatAll((Date)beforeValue);
			String afterTime =DateUtil.formatAll((Date)afterValue);
			if(!beforeTime.equals(afterTime)) {
				isChange = true;
			}
		} else if(typeName.equals("java.util.Date")){
			
		}else if(typeName.equals("com.ethink.frame.entity.BaseNullEntity")) { // 其他实体，比较ID是否一样
			if(((NullEntity)beforeValue).getId() - ((NullEntity)afterValue).getId() != 0L) {
				isChange = true;
			}
		}
		return isChange;
	}
	
	private static List<String> longToString(int[] keys) {
		List<String> list = new ArrayList<String>();
		if(keys != null && keys.length != 0) {
			for(long e : keys) {
				list.add(String.valueOf(e));
			}
		}
		
		return list;
	}
	
	private static String keyToText(String key, List<String> keys, String[] texts) {
		String val = "";
		int idx = keys.indexOf(key);
		if(idx != -1) {
			val = texts[idx];
		}
		
		return val;
	}
}
